using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class PlayerCharacter : MonoBehaviour
{
    //UI part
    private int coinNum;
    public GameObject windPowerUI;
    private FlyEnergy EnergyBarUI;
    public GameObject CoinTextUI;

    public BirdController birdCc;
    public HumanController humanCc;
    public GameObject birdCameraRig;



    public Transform birdModel;
    public Transform humanModel;

    public Animator cameraAnimator;
    public Transform birdHud;

    // config area
    public float birdSpeedUpCost;
    public float powerRecoverSpeed; // per second
    public float lowestSpeedUpWindPower;

    public float birdNormalCost;

    public float minStartFlyGroundDist;
    
    public float maxRecoverPower;


    // common status area
    public bool isBird;
    public float maxWindPower;

    public float currWindPower;

    // human area
    private bool isGrounded;
    private bool jumping;
    private bool falling;

    public float moveSpeed;
    public float jumpSpeed;

    public float gravityVel;
    public AirCannonWeapon airCannonWeapon;
    private Vector3 moveVelocity;

    // bird area
    public bool isSpeedUp;

    public bool isHit;

    public Rigidbody rigid;

    Vector3 vel;

    CharacterController characterController;

    public Animator animator;

    public ParticleSystem particle;
    private void Awake()
    {
        rigid = GetComponent<Rigidbody>();
        Cursor.lockState = CursorLockMode.Locked;
        characterController = GetComponent<CharacterController>();

        EnergyBarUI = windPowerUI.GetComponentInChildren<FlyEnergy>();
    }
    void Start()
    {
        coinNum = 0;
        // currWindPower = 0;
        // maxWindPower = 100;
        EnergyBarUI.SetRealEnergy(0);


        isBird = false;
        setBirdStatus(false);
        setHumanStatus(true);
        cameraAnimator.Play("Human");
        isHit = true;
        rigid.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ | RigidbodyConstraints.FreezeRotationY;
        rigid.isKinematic = true;
        vel = new Vector3(0, 0, 0);
    }

    // Update is called once per frame
    void Update()
    {
        if (isBird && isHit)
        {
            Debug.Log("hit");
            ChangeCharacterStatus();
        }
        // Debug.Log("Windpower"+currWindPower);
        EnergyBarUI.SetRealEnergy(currWindPower);
    }

    private void FixedUpdate()
    {
        // cost the wind power
        isHit = false;
        GroundDetect();

        // disable rigid while human use charactercontroller instead
        // if (!isBird && !isGrounded)
        // {
        //     // individual gravity
        //     // https://answers.unity.com/questions/1543639/how-to-set-individual-rigidbody-gravity-solved.html
        //     rigid.AddForce(Physics.gravity * (rigid.mass * rigid.mass));
        // }

        //simulate gravity

        // if (isBird && isHit)
        // {
        //     Debug.Log("hit");
        //     ChangeCharacterStatus();
        // }

        if (isBird && isSpeedUp)
        {
            currWindPower -= birdSpeedUpCost * Time.deltaTime;
        }
        else if (isBird && !isSpeedUp)
        {
            currWindPower -= birdNormalCost * Time.deltaTime;
        }

        // check enough wind power to fly
        if (isBird && currWindPower <= 0)
        {
            ChangeCharacterStatus();
            currWindPower = 1;
        }

        if (!isBird)
        {
            if (currWindPower < maxRecoverPower)
            {    
                currWindPower = currWindPower + powerRecoverSpeed * Time.deltaTime > maxRecoverPower
                    ? maxRecoverPower : currWindPower + powerRecoverSpeed * Time.deltaTime;
            }
            // rigid.velocity = moveVelocity; 
            characterController.Move(vel * Time.deltaTime);
            if (vel.x <= 0.2f && vel.z <= 0.2f)
            {
                animator.SetBool("Running", false);
            }
            else
            {
                animator.SetBool("Running", true);
            }

            if (!characterController.isGrounded)
            {
                vel.y += Physics.gravity.y * gravityVel * Time.deltaTime;
            }
        }
    }

    //Author:Hu 
    public void SetWindPower(float value)
    {
        currWindPower += value;
        if (currWindPower < 0)
        {
            currWindPower = 0;
        }
        if (currWindPower > maxWindPower)
        {
            currWindPower = maxWindPower;
        }

        EnergyBarUI.SetRealEnergy(currWindPower);
    }

    //Author: HU
    public void AddCoin(int value)
    {
        coinNum+=value;
        CoinTextUI.GetComponent<CoinNum>().changeTxt(coinNum);
    }

    public int GetCoinNum()
    {
        return coinNum;
    }

    public void ChangeCharacterStatus()
    {
        if (isBird)//change to human
        {
            setHumanStatus(true);
            birdHud.gameObject.SetActive(false);
            setBirdStatus(false);
            cameraAnimator.Play("Human");

            //rigid area
            rigid.isKinematic = true;
            rigid.velocity = Vector3.zero;
            rigid.angularVelocity = Vector3.zero;
            rigid.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ | RigidbodyConstraints.FreezeRotationY;

            // transform reset
            // transform.rotation = Quaternion.Euler(0, transform.rotation.y, 0);

            // 使得回到人形态后，forward朝向和鸟的forward朝向在xoz平面的分量方向一致
            var q1 = Quaternion.FromToRotation(transform.up, Vector3.up);
            transform.rotation = q1 * transform.rotation;

            birdCc.controller.resetMouseAim(transform.rotation);

            // transform.forward = transform.
            isSpeedUp = false;
            birdCc.setMouseFlightStatus(false);
            vel = Vector3.zero;
            characterController.enabled = true;
        }
        else//cahnge to bird
        {
            birdCc.controller.resetMouseAim(transform.rotation);
            birdCc.setMouseFlightStatus(true);
            setBirdStatus(true);
            setHumanStatus(false);
            transform.position += new Vector3(0, 2, 0);
            birdHud.gameObject.SetActive(true);
            cameraAnimator.Play("Bird");
            rigid.isKinematic = false;
            //unlock rotation
            rigid.constraints = RigidbodyConstraints.None; ;
            characterController.enabled = false;
        }

        //TODO: change effects
        isBird = !isBird;
        particle.Play();
    }

    public bool canChangeToBird()
    {
        //TODO: change status limiattion
        RaycastHit hit;
        if (Physics.Raycast(transform.position, -transform.up, out hit, minStartFlyGroundDist))
        {
            Debug.Log(false);
            return false;
        }

        return currWindPower - birdNormalCost > lowestSpeedUpWindPower;
    }

    public bool canSpeedUp()
    {
        return currWindPower > lowestSpeedUpWindPower;
    }

    void setHumanStatus(bool isHuman)
    {
        humanModel.gameObject.SetActive(isHuman);
        humanCc.enabled = isHuman;
        // rigid.constraints
        // human.gameObject.SetActive(isHuman);
    }

    void setBirdStatus(bool isBird)
    {
        birdCc.enabled = isBird;
        birdModel.gameObject.SetActive(isBird);
        birdHud.gameObject.SetActive(isBird);
        birdCameraRig.SetActive(isBird);
    }

    // void humanUpdate()
    // {
    //     rigid.velocity = moveVelocity;
    //     if (isGrounded)
    //     {
    //         jumping = false;
    //         falling = false;
    //     }
    //     else if (rigid.velocity.y < 0)
    //     {
    //         falling = true;
    //     }
    // }

    private void GroundDetect()
    {
        Vector3 rayOriginPos = transform.position;
        Debug.DrawLine(rayOriginPos, new Vector3(rayOriginPos.x, rayOriginPos.y - 1, rayOriginPos.z), Color.red);

        RaycastHit hit;
        if (Physics.Raycast(rayOriginPos, -transform.up, out hit, 1f))
        {
            isGrounded = true;
            animator.SetBool("isGrounded", true);
        }
        else
        {
            animator.SetBool("isGrounded", false);
            isGrounded = false;
        }
    }

    // public void Move(float xSpeed, float zSpeed)
    // {
    //     moveVelocity.x = xSpeed * speed;
    //     moveVelocity.z = zSpeed * speed;

    //     float blend = Mathf.Abs(xSpeed) > Mathf.Abs(zSpeed) ? Mathf.Abs(xSpeed) : Mathf.Abs(zSpeed);
    // }

    // public void Move(Vector3 direction, float speed)
    // {
    //     direction = direction.normalized;

    //     moveVelocity = new Vector3(direction.x * speed, moveVelocity.y, direction.z * speed);
    //     direction = new Vector3(-direction.z, 0, direction.x);
    // }

    public void Move(Vector3 dir)
    {
        dir = dir.normalized;
        vel.x = dir.x * moveSpeed;
        vel.z = dir.z * moveSpeed;
    }
    public void Jump()
    {
        vel.y = jumpSpeed;
        animator.SetTrigger("Jump");
    }

    public void Jump(float speed)
    {
        vel.y = speed;
    }

    public void startBirdSpeedUp()
    {
        isSpeedUp = true;
    }
    public void stopBirdSpeedUp()
    {
        isSpeedUp = false;
    }

    private void OnCollisionStay(Collision other)
    {
        if (other.gameObject.CompareTag("Bonus"))
        {
            isHit = false;
        }
        else
        {
            isHit = true;
        }
    }

    private void OnCollisionExit(Collision other)
    {
        isHit = false;
    }

    private void OnDrawGizmos()
    {
        Gizmos.DrawLine(transform.position, transform.position - Vector3.up * minStartFlyGroundDist);
    }

}
